package com.bwie.es.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.bwie.common.domain.IndexInfoReq;
import com.bwie.common.domain.IndexInfoResp;
import com.bwie.common.result.Result;
import com.bwie.es.service.EsIndexService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@Slf4j
public class EsIndexServiceImpl implements EsIndexService {

    @Resource
    private RestHighLevelClient restHighLevelClient;


    @Override
    public Result createIndex(IndexInfoReq indexInfoReq) {
        log.info("Es索引的创建:{}", JSONObject.toJSONString(indexInfoReq));
        //判断索引是否存在
        Boolean exitIndex = isExitIndex(indexInfoReq.getIndexName());
        if(exitIndex){
            throw new RuntimeException(indexInfoReq.getIndexName()+"索引存在");
        }
        //创建
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexInfoReq.getIndexName());
        if(indexInfoReq.getIndexMapping()!=null){
            String jsonString = JSONObject.toJSONString(indexInfoReq.getIndexMapping());
            createIndexRequest.mapping(jsonString, XContentType.JSON);
        }

        try {
            restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException("Es索引创建失败");
        }
        return Result.success("索引创建成功");
    }

    @Override
    public Result deleteIndex(String indexName) {
        //判断索引名称是否存在
        Boolean exitIndex = isExitIndex(indexName);
        if(exitIndex){
            DeleteIndexRequest request = new DeleteIndexRequest(indexName);
            try {
                AcknowledgedResponse response = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
                if(response.isAcknowledged()){
                    return Result.success("删除成功");
                }else {
                    return Result.error("删除失败");
                }
            } catch (IOException e) {
                throw new RuntimeException("删除失败"+e.getMessage());
            }

        }else {
            return Result.error("索引不存在");
        }
    }

    @Override
    public Boolean isExitIndex(String indexName) {
        GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);

        try {
            boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
               return exists;
        } catch (IOException e) {
            throw new RuntimeException("查询异常");
        }
    }

    @Override
    public IndexInfoResp getIndex(String indexName) {
        //索引名称是否存在
        Boolean exitIndex = isExitIndex(indexName);
        if(exitIndex){
            GetIndexRequest request = new GetIndexRequest(indexName);

            try {
                //创建返回对象
                IndexInfoResp indexInfoResp = new IndexInfoResp();
                GetIndexResponse getIndexResponse = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);
                //给返回对象复制
                indexInfoResp.setIndexName(getIndexResponse.getIndices()[0]);
                indexInfoResp.setMappings(getIndexResponse.getMappings().get(indexName).getSourceAsMap());
                Settings settings = getIndexResponse.getSettings().get(indexName);
                Set<String> keySet = settings.keySet();
                HashMap<String, Object> map = new HashMap<>();
                keySet.forEach(key ->{
                    map.put(key,settings.get(key));
                });
                indexInfoResp.setSettings(map);

                Map<String, List<AliasMetadata>> aliases = getIndexResponse.getAliases();
                Map<String,Object> aliasesMap = JSONObject.parseObject(JSONObject.toJSONString(aliases), Map.class);
               indexInfoResp.setAliases(aliasesMap);

               return indexInfoResp;

            } catch (IOException e) {
                throw new RuntimeException("获取索引失败");
            }

        }else {
            throw new RuntimeException("索引不存在");
        }
    }

    @Override
    public Result updateIndex(IndexInfoReq indexInfoReq) {
        log.info("ES索引的修改:{}",JSONObject.toJSONString(indexInfoReq));
        //判断索引是否存在
        Boolean exitIndex = isExitIndex(indexInfoReq.getIndexName());
        if(!exitIndex){
            throw new RuntimeException(indexInfoReq.getIndexName()+"索引不存在");
        }
        //修改的索引信息
        Map<String, Object> updateSettings = indexInfoReq.getSettings();
        Map<String, Object> updateMappings = indexInfoReq.getIndexMapping();
        //创建修改请求
        PutMappingRequest putMappingRequest = new PutMappingRequest(indexInfoReq.getIndexName());
        if(updateMappings!=null){
            putMappingRequest.source(updateMappings);
        }
        UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(indexInfoReq.getIndexName());
        if(updateSettings!=null){
            updateSettingsRequest.settings(updateSettings);
        }
        try {
            //执行修改操作
            restHighLevelClient.indices().putMapping(putMappingRequest,RequestOptions.DEFAULT);
            restHighLevelClient.indices().putSettings(updateSettingsRequest,RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException("Es索引修改失败");
        }
        return Result.success("索引修改成功");
    }

}
